#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "base.h"
#include "service.h"
#include "msg.h"
#include "http.h"
#include "cfg.h"
#include "hidb.h"

#define MODULE	"SEARCH_SELECTOR_V001"

#define USAGE		"Usage: %s [-vh] [-f <filename>] ..."		\
 " \nOptions:"													\
 " \n  -h            Show Usage"								\
 " \n  -v            Show Version"								\
 " \n  -f filename   Specify a Configure file"					\
 " \n\n"

typedef struct TASK_LOAD {
	void	*buf;
	int		buflen;
} TASK_LOAD;

static int master_ontask(TASK * task, const THREAD * master)
{
	assert(task && master);

	SERVICE * p = (SERVICE *)master->sys;
	assert(p);

	TASK_LOAD *data = (TASK_LOAD *)task->data;
	if (conn_wlist_add(p->ifaces[0], data->buf, data->buflen) < 0) {
		send_log(LV_ERROR, "#master_ontask# wlist add");
		return -1;
	}

	send_log(LV_DEBUG, "%s send msg", TTAG(master));

	free(data);
	free(task);

	return 0;
}

int master_onpack(char * pack, int headlen, int packlen, 
		int scode, const void * obj)
{
	assert(pack && headlen == MSG_HEAD_LEN && packlen >= MSG_HEAD_LEN && obj);

	SERVICE * p = (SERVICE * )obj;

	send_log(LV_DEBUG, "%s on packet {%s}", TTAG(p->master), (char *)pack);

	return 0;
}

static int ontiming(const void * obj)
{
	THREAD * p = (THREAD *)obj;
	assert(p);

	//TODO select from hidb

	char * url = "http://www.baidu.com/";
	LOAD_PARAM param = {strlen(url), 0, "220.181.6.81", url, NULL}; 

	int buflen;
	char * buf = msg_load_req_new(&buflen, 1, &param);
	if (!buf) {
		send_log(LV_ERROR, "#ontiming# req new");
		return -1;
	}

	TASK * task = malloc(sizeof(struct TASK));
	if (!task) {
		send_log(LV_ERROR, "#ontiming# task malloc()");
		return -2;
	}

	TASK_LOAD * data = malloc(sizeof(struct TASK_LOAD));
	if (!data) {
		send_log(LV_ERROR, "#ontiming# task_load malloc()");
		return -3;
	}

	data->buflen = buflen;
	data->buf = buf;
	task->data = data;

	if (send_response(task, p) < 0) {
		send_log(LV_ERROR, "#ontiming# send task");
		free(buf);
		free(data);
		free(task);
		return -1;
	}

	send_log(LV_DEBUG, "on timer");

	return 0;
}

int main(int argc, char ** argv)
{
	const char * cfg_path = NULL;
	char c;
	while ((c = getopt(argc, argv, "f:vh")) != -1) {
		switch(c){
		case 'f':
			cfg_path = optarg;
			break;
		case 'h':
			fprintf(stdout, USAGE, argv[0]);
			exit(0);
		case 'v':
			version(MODULE);
			exit(0);
		default:
			fprintf(stderr, USAGE, argv[0]);
			exit(1);
		}
	}
	
	CFGMAP * cfg = cfg_new();
	if (!cfg) exit(2);

	if (cfg_path && cfg_load(cfg, cfg_path) < 0) {
		fprintf(stderr, USAGE, argv[0]);
		exit(3);
	} else if (cfg_load(cfg, "selector.ini") < 0) {
		fprintf(stderr, "selector.ini not found");
		exit(4);
	}
	
	cfg_dump(cfg);
	
	unsigned int conns_num = cfg_get_int(cfg, "core:conns_num", 0);
	if (!conns_num) exit(5);

	int i;
	for (i = 0; i < conns_num; i ++) {
		char key[32];

		sprintf(key, "conn%d:ip", i);
		const char * ip = cfg_get_str(cfg, key, NULL);

		sprintf(key, "conn%d:port", i);
		int port = cfg_get_int(cfg, key, 0);

		if (!ip || !port) exit(6);

		service_add_iface(TYPE_CLIENT, ip, port, msg_depack, master_onpack);
	}


	unsigned int timer_usec = cfg_get_int(cfg, "core:intv_usec", 0);
	if (!timer_usec) exit(7);

	service_add_timing(timer_usec, ontiming, NULL, NULL, NULL);

	service_set_master(master_ontask, NULL, NULL);

	service_set_log_level(cfg_get_int(cfg, "log:level", LV_ERROR));

	service_set_log(cfg_get_str(cfg, "log:fatal", NULL), 
		LV_FATAL, cfg_get_int(cfg, "log:fatal_size", 1024));

	service_set_log(cfg_get_str(cfg, "log:error", NULL), 
		LV_ERROR, cfg_get_int(cfg, "log:error_size", 1024));

	service_set_log(cfg_get_str(cfg, "log:sys", NULL), 
		LV_SYS, cfg_get_int(cfg, "log:sys_size", 1024));

	service_set_log(cfg_get_str(cfg, "log:warn", NULL), 
		LV_WARN, cfg_get_int(cfg, "log:warn_size", 1024));

	service_set_log(cfg_get_str(cfg, "log:info", NULL), 
		LV_INFO, cfg_get_int(cfg, "log:info_size", 1024));

	service_set_log(cfg_get_str(cfg, "log:debug", NULL), 
		LV_DEBUG, cfg_get_int(cfg, "log:debug_size", 1024));

	service_set_pid_path(cfg_get_str(cfg, "core:pid_path", NULL));


	service_run();
	return 0;
}

